#include "main.h"
#include "fft.h"
#include "adc.h"
#include "tim.h"
#include "stdio.h"
#include "arm_math.h"
#include "arm_const_structs.h"
#include "oled.h"

#define POINTS 4096
#define FFT_LENGTH POINTS
#define TRIGGER_LEVEL 0.02

uint16_t adc_buff[POINTS];//存放ADC采集的数据
/* 
AdcConvEnd用来检测ADC是否采集完毕
0：没有采集完毕
1：采集完毕，在stm32f4xx_it里的DMA完成中断进行修改
 */
__IO uint8_t AdcConvEnd = 0;

float max_voltage[2], min_voltage[2], fft_delta_f = 0;
float fft_inputbuf[FFT_LENGTH * 2], fft_outputbuf[FFT_LENGTH], fftshift_outputbuf[FFT_LENGTH/2+1];
float peak_indices[POINTS/2+1];
extern char OLEDBuffer1[16], OLEDBuffer2[16], OLEDBuffer3[16], OLEDBuffer4[16];

float wave_capture(unsigned char channel){
	HAL_ADC_Stop_DMA(&hadc1);
	HAL_ADC_Stop_DMA(&hadc2);
	AdcConvEnd = 0;
	if(channel == 1) HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buff, POINTS); //让ADC1去采集POINTS个数，存放到adc_buff数组釿
	else if(channel == 2) HAL_ADC_Start_DMA(&hadc2, (uint32_t *)adc_buff, POINTS);
	while (!AdcConvEnd) //等待转换完毕
			;
	max_voltage[channel] = adc_buff[0] * 3.3 / 4095;
	min_voltage[channel] = adc_buff[0] * 3.3 / 4095;
	for (uint16_t i = 0; i < POINTS; i++){
		if(adc_buff[i] * 3.3 / 4095 > max_voltage[channel]) max_voltage[channel] = adc_buff[i] * 3.3 / 4095;
		if(adc_buff[i] * 3.3 / 4095 < min_voltage[channel]) min_voltage[channel] = adc_buff[i] * 3.3 / 4095;
	}
	printf("%.0f\n", max_voltage[channel] - min_voltage[channel]);
	HAL_ADC_Stop_DMA(&hadc1);
	HAL_ADC_Stop_DMA(&hadc2);
	max_voltage[channel] = adc_buff[0] * 3.3 / 4095;
	min_voltage[channel] = adc_buff[0] * 3.3 / 4095;
	for (uint16_t i = 0; i < POINTS; i++){
		if(adc_buff[i] * 3.3 / 4095 > max_voltage[channel]) max_voltage[channel] = adc_buff[i] * 3.3 / 4095;
		if(adc_buff[i] * 3.3 / 4095 < min_voltage[channel]) min_voltage[channel] = adc_buff[i] * 3.3 / 4095;
	}
	return max_voltage[channel] - min_voltage[channel];
}

void fft(){
	fft_delta_f = SystemCoreClock/2.0/((htim3.Init.Prescaler+1.0)*(htim3.Init.Period+1.0))/POINTS;
	for (int i = 0; i < FFT_LENGTH; i++){
		fft_inputbuf[i * 2] = /*0.5*(1-cos(2*PI*i/FFT_LENGTH))*/adc_buff[i] * 3.3 / 4095;//实部赋忼＿* 3.3 / 4095是为了将ADC采集到的值转换成实际电压
		fft_inputbuf[i * 2 + 1] = 0;//虚部赋忼，固定丿0.
	}
	arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1);
	arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH);
	fft_outputbuf[0] /= FFT_LENGTH;
	for (int i = 1; i < FFT_LENGTH; i++){//输出各次谐波幅忿
		fft_outputbuf[i] /= (FFT_LENGTH/2);
	}
	for (int i = 0; i < FFT_LENGTH/2+1; i++) fftshift_outputbuf[i] = fft_outputbuf[i];
	
	printf("-------------------------\nSpectrum Measurement:\n");
	printf("fft_delta_f: %.2f Hz\n", fft_delta_f);
	printf("f[0 Hz]:\t%.2fV\n", fftshift_outputbuf[0]);
	for (int i = 1; i < FFT_LENGTH/2+1; i++)//输出各次谐波幅忿
	{
		if(fftshift_outputbuf[i] >= TRIGGER_LEVEL){
			printf("f[%d Hz]:\t%.2fV ", (int)(i*fft_delta_f + 0.5), fftshift_outputbuf[i]);
			for(int j=TRIGGER_LEVEL/0.01; j<fftshift_outputbuf[i]/0.01; j++) printf("-");
			printf("\n");
		}
	}
	printf("-------------------------\n");
}

void display_time_domain_measure(unsigned char channel){
//	for (uint16_t i = 0; i < POINTS; i++){
//		printf("t[%d]:\t%.3fV\n", i, adc_buff[i] * 3.3 / 4095); //数据打印，查看结枿
//	}
	printf("-------------------------\nTime Domain Measurement:\n");
	printf("Vmax:\t%.3f V\n", max_voltage[channel]);
	printf("Vmin:\t%.3f V\n", min_voltage[channel]);
	printf("Vpp:\t%.3f V\n", max_voltage[channel] - min_voltage[channel]);
	OLED_ShowString(16,0,"Time Measure",16);
	OLED_ShowString(16,2,OLEDBuffer2,16);
	sprintf(OLEDBuffer2, "Vmax: %.3fV", max_voltage[channel]);
	OLED_ShowString(16,2,OLEDBuffer2,16);
	sprintf(OLEDBuffer3, "Vmin: %.3fV", min_voltage[channel]);
	OLED_ShowString(16,4,OLEDBuffer3,16);
	sprintf(OLEDBuffer4, "Vpp:  %.3fV", max_voltage[channel] - min_voltage[channel]);
	OLED_ShowString(16,6,OLEDBuffer4,16);
}
